package br.uff.javaavancado.dao.controle;

import br.uff.javaavancado.dao.generic.ExecutorDeBuscas;
import java.lang.reflect.Method;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class InterceptadorDeDAO implements MethodInterceptor {
    /* Parametros:
     * 
     * objeto - "this", o objeto "enhanced", isto �, o proxy.
     * 
     * metodo - o m�todo interceptado. 
     * 
     * args - um array de args; tipos primitivos s�o empacotados.
     * 
     * metodoProxy - utilizado para executar um m�todo super.
     * 
     * MethodProxy  -  Classes  geradas pela  classe Enhancer passam 
     * este objeto para o objeto MethodInterceptor registrado quando
     * um m�todo  interceptado �  executado.  Ele pode ser utilizado
     * para  invocar o  m�todo  original,  ou  chamar o mesmo m�todo
     * sobre um objeto diferente do mesmo tipo.
     */

    public Object intercept(Object objeto,
            Method metodo,
            Object[] args,
            MethodProxy metodoDoProxy)
            throws Throwable {
        // O s�mbolo ? representa um tipo desconhecido.
        ExecutorDeBuscas<?> daoGenerico = (ExecutorDeBuscas<?>) objeto;

//        String nomeDoMetodo = metodo.getName();

        if (metodo.isAnnotationPresent(MetodoRecuperaLista.class)) {
            //Recupera lista encontrado
            return daoGenerico.buscaLista(metodo, 
                    args, 
                    metodo.getAnnotation(MetodoRecuperaLista.class).namedQuery());
            
        } else if (metodo.isAnnotationPresent(MetodoRecuperaConjunto.class)) {
            //Recupera conjunto encontrado
            return daoGenerico.buscaConjunto(metodo, 
                    args, 
                    metodo.getAnnotation(MetodoRecuperaConjunto.class).namedQuery());
            
        } else if (metodo.isAnnotationPresent(MetodoRecuperaPrimeiro.class)) {
            //Recupera primeiro encontrado
            return daoGenerico.buscaUltimoOuPrimeiro(metodo, 
                    args, 
                    metodo.getAnnotation(MetodoRecuperaPrimeiro.class).namedQuery());
            
        } else if (metodo.isAnnotationPresent(MetodoRecuperaUltimo.class)) {
            //Recupera ultimo encontrado
            return daoGenerico.buscaUltimoOuPrimeiro(metodo, 
                    args, 
                    metodo.getAnnotation(MetodoRecuperaUltimo.class).namedQuery());
            
        } else if (metodo.isAnnotationPresent(MetodoRecupera.class)) {
            //Recupera encontrado
            return daoGenerico.busca(metodo, 
                    args, 
                    metodo.getAnnotation(MetodoRecupera.class).namedQuery());
            
        } else {
            //Metodo sem anotacao, ou seja, metodo mais especifico, chamando 
            // a implementacao especifica. Ex.: ClienteDAOImpl
            return metodoDoProxy.invokeSuper(objeto, args);
        }
    }

}
